package von.seiji.cn.test;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.img.Img;
import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.text.csv.CsvUtil;
import cn.hutool.http.ContentType;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.junit.Test;
import org.opencv.core.*;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;
import org.opencv.videoio.VideoCapture;
import von.seiji.cn.PointUtil;
import von.seiji.cn.other.CVUtil;

import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.Charset;

public class 人脸识别 {

    static {
//        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
        URL resource = T1.class.getClassLoader().getResource("data/opencv_java430.dll");
        URL resource1 = T1.class.getClassLoader().getResource("data/opencv_videoio_ffmpeg430_64.dll");
        try {
            //System.load("/root/opencv_build/opencv/build/lib/libopencv_java430.so");
            System.load(URLDecoder.decode(resource.getPath(), Charset.defaultCharset().name()));
            System.load(URLDecoder.decode(resource1.getPath(), Charset.defaultCharset().name()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Test
    public void test34() {
        VideoCapture capture = new VideoCapture();
        capture.open(0);
        // rtsp://admin:12345@192.0.0.64:554/h264/ch1/main/av_stream
//        String path = "rtsp://admin:a12345678@192.168.1.64:554/Streaming/Channels/101?transportmode=unicast";
//        String path = "rtsp://admin:HuaWei123@192.168.1.90/LiveMedia/ch1/Media1";
//        String path = "rtsp://admin:HuaWei123@192.168.1.82/LiveMedia/ch1/Media1";
//        capture.open(path);
        //capture.open("F://car1.mp4");
        if (!capture.isOpened()) {
            System.out.println("could not load video data...");
            return;
        }
        int frame_width = (int) capture.get(3);
        int frame_height = (int) capture.get(4);
        ImageGUI gui = new ImageGUI();
        // gui.createWin("OpenCV + Java视频读与播放演示", new Dimension(frame_width, frame_height));
        gui.createWin("OpenCV + Java视频读与播放演示");
        Mat frame = new Mat();
        int count = 0;
//        Mat imread = Imgcodecs.imread("C:\\Users\\Administrator\\Documents\\微信图片_20210805040649.jpg");
        JSONObject object = new JSONObject();
        object.put("image_type", "BASE64");
        object.put("show", true);
        while (true) {
            boolean have = capture.read(frame);
             Core.flip(frame, frame, 1);// Win上摄像头
            if (!have) break;
            if (!frame.empty()) {
                count++;
                face_recognize(frame);
                BufferedImage bufferedImage = convert2Image(frame);
                gui.imshow(bufferedImage);
//                byte[] bytes = mat2Byte(frame, JPG);
//                face_recognize(frame);

//                byte[] bytes = PointUtil.mat2Byte(frame, ".jpg");
//
//                object.put("image", Base64.encode(bytes));
//                String post = HttpUtil.post("http://192.168.1.16:7777/ai-skill/baidu/api/helmet", object.toString());
//                BufferedImage image = ImgUtil.toImage(((JSONObject) JSON.parseObject(post)).getString("image"));

//http://192.168.1.16:7777/ai-skill/baidu/api/helmet

//                gui.imshow(convert2Image(frame));
//                gui.imshow(image);
            } else {
                break;
            }
        }
    }


    /**
     * OpenCV-4.0.0 人脸识别
     *
     * @return: void
     * @date: 2019年5月7日12:16:55
     */
    public void face_recognize(Mat image) {
        // 1 读取OpenCV自带的人脸识别特征XML文件
//        CascadeClassifier facebook = new CascadeClassifier("src/main/resources/data/haarcascade_frontalface_alt.xml");
        CascadeClassifier facebook = new CascadeClassifier("C:\\Users\\Administrator\\Desktop\\temp\\seiji2util\\src\\main\\resources\\data\\haarcascade_frontalface_alt.xml");
        // 2 读取测试图片
//            byte[] bytes = IoUtil.readBytes(new FileInputStream("C:\\Users\\Administrator\\Desktop\\111.jpg"));
//        Mat image = Imgcodecs.imdecode(new MatOfByte(bytes), Imgcodecs.IMREAD_COLOR);
        //Mat image = Imgcodecs.imread("C:\\Users\\Administrator\\Desktop\\20180428110528140.png");

        //image = imdecode(fromfile('中文.jpg', dtype=uint8), -1)
        //cv2.imencode('.jpg', img_data)[1].tofile(file_path)
        // 3 特征匹配
        MatOfRect face = new MatOfRect();
        facebook.detectMultiScale(image, face);
        // 4 匹配 Rect 矩阵 数组
        Rect[] rects = face.toArray();
        System.out.println("匹配到 " + rects.length + " 个人脸，位置坐标：" + JSON.toJSON(rects));
//        Mat mat = null;

        // 5 为每张识别到的人脸画一个圈
        for (int i = 0; i < rects.length; i++) {
            Imgproc.rectangle(image, new Point(rects[i].x, rects[i].y), new Point(rects[i].x + rects[i].width, rects[i].y + rects[i].height), new Scalar(0, 255, 0));
                Imgproc.putText(image, "Face", new Point(rects[i].x, rects[i].y), Imgproc.FONT_HERSHEY_SCRIPT_SIMPLEX, 1.0, new Scalar(0, 255, 0), 1, Imgproc.LINE_AA, false);
//                mat = new Mat(image, rects[i]);
        }

//        return mat;
    }


    /*

     */

    /**
     * OpenCV-4.0.0 人脸识别
     *
     * @return: void
     * @date: 2019年5月7日12:16:55
     *//*
    public Mat face_recognize(byte[] bytes,Mat mat) {
        // 1 读取OpenCV自带的人脸识别特征XML文件
       CascadeClassifier facebook=new CascadeClassifier("src/main/resources/data/haarcascade_frontalface_alt.xml");
        // 2 读取测试图片
//            byte[] bytes = IoUtil.readBytes(new FileInputStream("C:\\Users\\Administrator\\Desktop\\111.jpg"));
        Mat image = Imgcodecs.imdecode(new MatOfByte(bytes), Imgcodecs.IMREAD_COLOR);
        //Mat image = Imgcodecs.imread("C:\\Users\\Administrator\\Desktop\\20180428110528140.png");

        //image = imdecode(fromfile('中文.jpg', dtype=uint8), -1)
        //cv2.imencode('.jpg', img_data)[1].tofile(file_path)
        // 3 特征匹配
        MatOfRect face = new MatOfRect();
        facebook.detectMultiScale(image, face);
        // 4 匹配 Rect 矩阵 数组
        Rect[] rects=face.toArray();
        System.out.println("匹配到 "+rects.length+" 个人");

        ImageGUI gui = new ImageGUI();
        // gui.createWin("OpenCV + Java视频读与播放演示", new Dimension(frame_width, frame_height));
        gui.createWin("OpenCV + Java视频读与播放演示");

        // 5 为每张识别到的人脸画一个圈
        Mat mat = null;
        for (int i = 0; i < rects.length; i++) {
            Imgproc.rectangle(image,new Point(rects[i].x, rects[i].y), new Point(rects[i].x + rects[i].width, rects[i].y + rects[i].height), new Scalar(0, 255, 0));
            Imgproc.putText(image,"Body", new Point(rects[i].x, rects[i].y),Imgproc.FONT_HERSHEY_SCRIPT_SIMPLEX, 1.0, new Scalar(0, 255, 0),1,Imgproc.LINE_AA,false);
             mat = new Mat(image, rects[i]);
        }

        gui.imshow(convert2Image(mat));
    }
    */
    public static Mat byte2Mat(byte[] bytes) {
        return Imgcodecs.imdecode(new MatOfByte(bytes), Imgcodecs.IMREAD_UNCHANGED);
    }

    public static final String JPG = ".jpg";
    public static final String PNG = ".png";

    public static byte[] mat2Byte(Mat mat, String ext) {
        MatOfByte aByte = new MatOfByte();
        Imgcodecs.imencode(ext, mat, aByte);
        return aByte.toArray();
    }


    public static BufferedImage convert2Image(Mat matrix) {
        int type = BufferedImage.TYPE_BYTE_GRAY;
        if (matrix.channels() > 1) {
            type = BufferedImage.TYPE_3BYTE_BGR;
        }
        int bufferSize = matrix.channels() * matrix.cols() * matrix.rows();
        byte[] buffer = new byte[bufferSize];
        matrix.get(0, 0, buffer);
        // 获取所有的像素点
        BufferedImage image = new BufferedImage(matrix.cols(), matrix.rows(), type);
        final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
        System.arraycopy(buffer, 0, targetPixels, 0, buffer.length);
        return image;
    }


 /*     public static BufferedImage convert2Image(Mat mat) {
        int width = mat.cols();
        int height = mat.rows();
        int dims = mat.channels();
        int[] pixels = new int[width * height];
        byte[] rgbdata = new byte[width * height * dims];
        mat.get(0, 0, rgbdata);
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        int index = 0;
        int r = 0, g = 0, b = 0;
        for (int row = 0; row < height; row++) {
            for (int col = 0; col < width; col++) {
                if (dims == 3) {
                    index = row * width * dims + col * dims;
                    b = rgbdata[index] & 0xff;
                    g = rgbdata[index + 1] & 0xff;
                    r = rgbdata[index + 2] & 0xff;
                    pixels[row * width + col] = ((255 & 0xff) << 24) | ((r & 0xff) << 16) | ((g & 0xff) << 8) | b & 0xff;
                }
                if (dims == 1) {
                    index = row * width + col;
                    b = rgbdata[index] & 0xff;
                    pixels[row * width + col] = ((255 & 0xff) << 24) | ((b & 0xff) << 16) | ((b & 0xff) << 8) | b & 0xff;
                }
            }
        }
        setRGB(image, 0, 0, width, height, pixels);
        return image;
    }

        public static void setRGB(BufferedImage image, int x, int y, int width, int height, int[] pixels) {
        int type = image.getType();
        if (type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB)
            image.getRaster().setDataElements(x, y, width, height, pixels);
        else
            image.setRGB(x, y, width, height, pixels, 0, width);
    }*/



    /*  byte * matToBytes(Mat image)
    {
        int size = image.total() * image.elemSize();
        byte * bytes = new byte[size];  // you will have to delete[] that later
        std::memcpy(bytes,image.data,size * sizeof(byte));
    }




    Mat bytesToMat(byte * bytes,int width,int height)
    {
        Mat image = Mat(height,width,CV_8UC3,bytes).clone(); // make a copy
        return image;
    }
    */

}
